#ifndef ED7209E5_99A9_497C_A1CE_2DBA8E732933
#define ED7209E5_99A9_497C_A1CE_2DBA8E732933
#pragma once
#include <iostream>
using namespace std;
#include "Log.hpp"
#include "Socket.hpp"
#include<poll.h>
#include <sys/time.h>

int defaultport = 8080;
static const int fd_num_max = 64; // 设置最大fd的默认值
int defaultfd = -1;                                 // 辅助数组默认初始值
int non_event = 0;

class PollServer
{
public:
    PollServer(uint16_t port = defaultport)
    : port_(port)
    {
        // 初始化pollfd数组
        for (int i = 0; i < fd_num_max; i++)
        {
            _event_fds[i].fd = defaultfd;
            _event_fds[i].events = non_event;
            _event_fds[i].revents = non_event;

            // cout << "fd_array[" << i << "]" << " : " << fd_array[i] << endl;
        }
    }
    ~PollServer()
    {
        listensock_.Close();
    }

    bool Init()
    {
        listensock_.InitSocket();
        listensock_.Bind(port_);
        listensock_.Listen();
        return true;
    }

    //
    void Accepter()
    {
        string clientip;
        uint16_t clientport = 0;
        int sock = listensock_.Accept(&clientip, &clientport);   //此时不会阻塞在这里， 因为新连接到来了我们才accept， 而不是先accept等待新连接到来。
        if (sock < 0) return;
        lg(Info, "accept success, %s: %d, sock fd : %d", clientip.c_str(), clientport, sock);   //链接成功
        //链接成功之后， 就是添加新需要关心的fd进入数组中。
        int pos = 1;
        for (;pos < fd_num_max; pos++)
        {
            if (_event_fds[pos].fd != defaultfd) continue;
            else break;
        }
        if (pos == fd_num_max)   //如果这个条件成立， 就说明pos加到了fd_num_max，而不是遇到了defaultfd。 就说明满了， 就把监听sock关掉。 
        {
            lg(Waring, "server is full, close %d now!", sock);
            close(sock);        

            //这里可以扩容
        }
        else   //遇到了defaultfd, 没满
        {
            _event_fds[pos].fd = sock;    //将defaultfd的位置设置为新连接的fd。
            _event_fds[pos].events = POLLIN;
            _event_fds[pos].revents = non_event;

            PrintFd();
        }
    }

    void Recver(int fd, int i)
    {
        char buffer[1024];
        ssize_t n = read(fd, buffer, sizeof(buffer) - 1); 
        if (n > 0)
        {
            buffer[n] = 0;

            cout << "get a message: " << buffer << endl;
        }
        else if (n == 0)  //等待超时，
        {
            lg(Info, "client quit, me too, close fd is : %d", fd);
            close(fd);
            _event_fds[i].fd = defaultfd;
        }
        else
        {
            lg(Waring, "recv error: fd is : %d", fd);   
            close(fd);
            _event_fds[i].fd = defaultfd;
        }

    }


    //
    void Dispatcher()
    {
        for (int i = 0; i < fd_num_max; i++)
        {   
            int fd = _event_fds[i].fd;  //得到合法文件描述符
            if (fd == defaultfd) continue;  //这个文件描述符不关心

            //然后根据rfds判断是否fd就绪
            if (_event_fds[i].revents & POLLIN)   //判断就绪
            {
                if (fd == listensock_.Fd())   //如果fd就是当前listensock_的fd， 说明有新连接岛链， 就链接。
                {
                    Accepter();    //链接管理器
                }
                else
                {
                    Recver(fd, i);  //读取管理器
                }
            }
        }
    }
    //
    void Start()
    {
        _event_fds[0].fd = listensock_.Fd();
        _event_fds[0].events = POLLIN;//新连接到来，事件类型等于读事件就绪。 所以这里设置成POLLIN， 表示读事件就绪。
        int timeout = 3000;


        for (;;)
        {
            int n = poll(_event_fds, fd_num_max, timeout);  //第一个数组元素， 第二个数组元素个数
            switch (n)
            {
            case 0:
                cout << "time out, timeout: " << endl;
                break;
            case -1:
                cerr << "poll error" << endl;
                break;
            default:
                // 有时间就绪了,TOOD
                cout << "get a link!!!" << endl;
                Dispatcher(); // 就绪的事件和fd怎么知道只有一个额？？
                // 处理
                break;
            }
        }
    }

    void PrintFd()
    {
        cout << "online fd list: ";
        for (int i = 0; i < fd_num_max; i++)
        {
            if (_event_fds[i].fd == defaultfd) continue;
            cout << _event_fds[i].fd << " ";
        }
        cout << endl;
    }

private:
    Socket listensock_;
    uint16_t port_;

    pollfd _event_fds[fd_num_max];   //这里可以使用vector

    // int fd_array[fd_num_max];
};


#endif /* ED7209E5_99A9_497C_A1CE_2DBA8E732933 */



    